<!doctype html>
<html>
<head>
  <title>Dropbox JavaScript SDK</title>
  <link rel="stylesheet" href="/styles.css">
  <script src="/__build__/Dropbox-sdk.min.js"></script>
</head>
<body>
  <!-- Example layout boilerplate -->
  <header class="page-header">
    <div class="container">
      <nav>
        <a href="/">
          <h1>
            <img src="https://cfl.dropboxstatic.com/static/images/brand/logotype_white-vflRG5Zd8.svg" class="logo" />
            JavaScript SDK Examples
          </h1>
        </a>
        <a href="https://github.com/dropbox/dropbox-sdk-js/tree/main/examples/javascript" class="view-source">View Source</a>
      </nav>
      <h2 class="code">
        <a href="/">examples</a> / upload file
      </h2>
    </div>
  </header>

  <!-- Example description and UI -->
  <section class="container main">
    <p>This example shows how to use the <code>Dropbox.filesUpload()</code> [<a href="http://dropbox.github.io/dropbox-sdk-js/Dropbox.html#filesUpload">docs</a>] method to upload a file.</p>

    <form onSubmit="return uploadFile()">
      <input type="text" id="access-token" placeholder="Access token" />
      <input type="file" id="file-upload" />
      <button type="submit">Submit</button>
    </form>

    <!-- A place to show the status of the upload -->
    <h2 id="results"></h2>

    <p class="info">To obtain an access token for quick testing, you can go to <a href="https://dropbox.github.io/dropbox-api-v2-explorer/#files_list_folder" target="_blank">API Explorer</a> click the "Get Token" button on the top right, copy the token it creates and then paste it here.</p>
  </section>

  <script>
    function uploadFile() {
        
      const UPLOAD_FILE_SIZE_LIMIT = 150 * 1024 * 1024;
      var ACCESS_TOKEN = document.getElementById('access-token').value;
      var dbx = new Dropbox.Dropbox({ accessToken: ACCESS_TOKEN });
      var fileInput = document.getElementById('file-upload');
      var file = fileInput.files[0];
      
      
      if (file.size < UPLOAD_FILE_SIZE_LIMIT) { // File is smaller than 150 MB - use filesUpload API
        dbx.filesUpload({path: '/' + file.name, contents: file})
          .then(function(response) {
            var results = document.getElementById('results');
            var br = document.createElement("br");
            results.appendChild(document.createTextNode('File uploaded!'));
            results.appendChild(br);
            console.log(response);
          })
          .catch(function(error) {
            console.error(error.error || error);
          });
      } else { // File is bigger than 150 MB - use filesUploadSession* API
        const maxBlob = 12 * 1024 * 1024; // 8MB - Dropbox JavaScript API suggested chunk size

        var workItems = [];
      
        var offset = 0;

        while (offset < file.size) {
          var chunkSize = Math.min(maxBlob, file.size - offset);
          workItems.push(file.slice(offset, offset + chunkSize));
          offset += chunkSize;
        } 
          
        const task = workItems.reduce((acc, blob, idx, items) => {
          if (idx == 0) {
            // Starting multipart upload of file
            return acc.then(function() {
              return dbx.filesUploadSessionStart({ close: false, contents: blob})
                        .then(response => response.result.session_id)
            });          
          } else if (idx < items.length-1) {  
            // Append part to the upload session
            return acc.then(function(sessionId) {
             var cursor = { session_id: sessionId, offset: idx * maxBlob };
             return dbx.filesUploadSessionAppendV2({ cursor: cursor, close: false, contents: blob }).then(() => sessionId); 
            });
          } else {
            // Last chunk of data, close session
            return acc.then(function(sessionId) {
              var cursor = { session_id: sessionId, offset: file.size - blob.size };
              var commit = { path: '/' + file.name, mode: 'add', autorename: true, mute: false };              
              return dbx.filesUploadSessionFinish({ cursor: cursor, commit: commit, contents: blob });           
            });
          }          
        }, Promise.resolve());
        
        task.then(function(result) {
          var results = document.getElementById('results');
          results.appendChild(document.createTextNode('File uploaded!'));
        }).catch(function(error) {
          console.error(error);
        });
        
      }
      return false;
    }
  </script>
</body>
</html>
